/**
 * 
 */
package ej.ea;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * PREFER ANNOTATIONS TO NAMING PATTERNS
 * 
 * Naming patterns may have typographical errors may result in silent failures.
 * There is no way to ensure that they are used only on appropriate program
 * elements. They provide no good way to associate parameter values with program
 * elements.
 * 
 * @author sunaina.sharma
 * 
 */
public class AnnotationVsNamingPattern {

	/**
	 * Indicates that the annotated method is a test method that must throw the
	 * designated exception to succeed.
	 */

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.METHOD)
	@interface ExceptionTest {
		Class<? extends Exception> value();
	}

	@ExceptionTest(ArithmeticException.class)
	public void m1() { // Test should pass
		int i = 0;
		i = i / i;
	}

	@ExceptionTest(ArithmeticException.class)
	public void m2() { // Should fail (wrong exception)
		int[] a = new int[0];
		int i = a[1];
	}

	@ExceptionTest(ArithmeticException.class)
	public void m3() {
	} // Should fail (no exception)

	/**
	 * @param args
	 * @throws ClassNotFoundException
	 */
	public static void main(String[] args) throws ClassNotFoundException {
		int tests = 0;
		int passed = 0;
		Class testClass = Class.forName("ej.ea.AnnotationVsNamingPattern");
		for (Method m : testClass.getDeclaredMethods()) {
			if (m.isAnnotationPresent(ExceptionTest.class)) {
				tests++;
				try {
					m.invoke(null);
					System.out.printf("Test %s failed: no exception%n", m);
				} catch (InvocationTargetException wrappedEx) {
					Throwable exc = wrappedEx.getCause();
					Class<? extends Exception> excType = m.getAnnotation(
							ExceptionTest.class).value();
					if (excType.isInstance(exc)) {
						passed++;
					} else {
						System.out.printf(
								"Test %s failed: expected %s, got %s%n", m,
								excType.getName(), exc);
					}
				} catch (Exception exc) {
					System.out.println("INVALID @Test: " + m);
				}
			}
		}
	}
}
